#ifndef RTE_KB1285_SPIRAM_H
#define RTE_KB1285_SPIRAM_H

#include "Arduino.h"
#include <QUAD_SPI.h>
#include "logger_rte.h"

using u8 = unsigned char;
using uint32_t = uint32_t;

class spiRam {
public:
    int begin(QUAD_SPI *, uint32_t, uint32_t);


    u8 get(int i) {
#ifdef SPIRAM_LOCK

        Rtos::mutex_lock(lock);
#endif
        u8 buf = 0xff;
        read(i, &buf, 1);
#ifdef SPIRAM_LOCK
        Rtos::mutex_unlock(lock);
#endif
        return buf;
    }

    u8 &operator[](int i) {
#ifdef SPIRAM_LOCK

        Rtos::mutex_lock(lock);
#endif
        u8 buf;
        read(i, &buf, 1);
#ifdef SPIRAM_LOCK
        Rtos::mutex_unlock(lock);
#endif
        return buf;
    }

    void set(int i, u8 val) {
#ifdef SPIRAM_LOCK

        Rtos::mutex_lock(lock);
#endif
        write(i, &val, 1);
        u8 buf = 0xff;
        read(i, &buf, 1);
#ifdef SPIRAM_LOCK
        Rtos::mutex_unlock(lock);
#endif
        if (val != buf) {
            logger.error("spiram write error 0x%x %d!=%d", i, buf, val);
        }
    }

    void fill(int v) {
#ifdef SPIRAM_LOCK

        Rtos::mutex_lock(lock);
#endif
        for (int i = 0; i < size; i += 4) {
            write(i, (u8 *) &v, 4);
        }
#ifdef SPIRAM_LOCK
        Rtos::mutex_unlock(lock);
#endif
    }

    uint32_t start, size;
    QUAD_SPI *sf;
#ifdef SPIRAM_LOCK
    static void *lock;
#endif

    int readBytes(size_t adr, u8 *buf, int length) {
#ifdef SPIRAM_LOCK
        Rtos::mutex_lock(lock);
#endif
        int res = read(adr, buf, length);
#ifdef SPIRAM_LOCK
        Rtos::mutex_unlock(lock);
#endif
        return res;
    };

    int writeBytes(uint32_t adr, u8 *buf, size_t length) {
#ifdef SPIRAM_LOCK
        Rtos::mutex_lock(lock);
#endif
        int res = write(adr, buf, length);
#ifdef SPIRAM_LOCK
        Rtos::mutex_unlock(lock);
#endif
        return res;
    };

private:
    int read(uint32_t addr, u8 *buf, uint32_t size);

    int write(uint32_t addr, u8 *buf, uint32_t size);

};

#endif // RTE_KB1285_SPIRAM_H
